package com.yubest.shiro.service.shiro;

import cn.hutool.json.JSONUtil;
import com.yubest.shiro.bean.Response;
import com.yubest.shiro.consts.Consts;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

/**
 * 自定义登陆过滤器
 *
 * 为了解决当未登陆时，请求需要权限的接口时，自动重定向到登陆接口问题
 * @see AccessControlFilter#saveRequestAndRedirectToLogin(ServletRequest, ServletResponse)
 *
 * @Author: hweiyu
 * @Date: 2022/11/9 10:25
 */
@Slf4j
public class MyFormAuthenticationFilter extends FormAuthenticationFilter {

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        if (this.isLoginRequest(request, response)) {
            if (this.isLoginSubmission(request, response)) {
                if (log.isTraceEnabled()) {
                    log.trace("Login submission detected.  Attempting to execute login.");
                }

                return this.executeLogin(request, response);
            } else {
                if (log.isTraceEnabled()) {
                    log.trace("Login page view.");
                }

                return true;
            }
        } else if (this.isOptionRequest(request)) {
            WebUtils.toHttp(response).setStatus(HttpStatus.OK.value());
            return true;
        } else {
            if (log.isTraceEnabled()) {
                log.trace("Attempting to access a path which requires authentication.  Forwarding to the Authentication url [" + this.getLoginUrl() + "]");
            }
            /**
             * 解决当未登陆时，请求需要权限的接口时，自动重定向到登陆接口问题，我们需要的是返回未登陆的状态而不是重定向
             */
            log.error("未登陆");
            HttpServletResponse resp = WebUtils.toHttp(response);
            resp.setContentType("application/json; charset=utf-8");
            resp.setCharacterEncoding("UTF-8");
            PrintWriter out = resp.getWriter();
            out.println(JSONUtil.toJsonStr(Response.error(Consts.NOT_LOGIN_CODE, "请先登陆")));
            out.flush();
            out.close();
            return false;
        }
    }

    private boolean isOptionRequest(ServletRequest request) {
        return RequestMethod.OPTIONS.name().equals(WebUtils.toHttp(request).getMethod());
    }
}
